﻿using System;
using System.Collections.Generic;
using NLog;
using NUnit.Framework;
using ScrappyDB.Attributes;
using ScrappyDB.BaseClasses;

namespace ScrappyDB.IntegrationTests.Core
{


    /// <summary>
    ///This is a test class for ArrayPropertyTests and is intended
    ///to contain all ArrayPropertyTests Unit Tests
    ///</summary>
    [TestFixture]
    public class ArrayPropertyTests
    {
        private static readonly Logger log = LogManager.GetCurrentClassLogger();

        public static Guid TestIdGuid = Guid.Empty;
        public static string TestString = "Test123";
        public static int TestInt = 1234;
        public static int TestNegativeInt = -5678;
        public static DateTime TestDate = DateTime.Now.ToUniversalTime();

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes

        //Use ClassInitialize to run code before running the first test in the class
        [TestFixtureSetUp]
        public  void Init()
        {
            try
            {
                Db db = new Db();
                db.Delete<EntityTestArrayTypes>(TestIdGuid);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        [TearDown]
        public void MyTestCleanup()
        {
            try
            {
                Db db = new Db();
                db.Delete<EntityTestArrayTypes>(TestIdGuid);
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }
        }

        #endregion




        [DomainName("ScrappyDB_UnitTests"), EntityName("EntityTestArrayTypes")]
        private class EntityTestArrayTypes : SdbEntity  //SdbEntity needed to support 'Tags'
        {
            public Guid Id { get; set; }
            public List<string> TestString { get; set; }
            public int[] TestInt { get; set; }
            public DateTime[] TestDateTime { get; set; }
        }

        [Test]
        public void SaveIntArrayTest()
        {
            Db target = new Db();
            var o = new EntityTestArrayTypes();
            o.Id = TestIdGuid;
            o.TestInt = new int[] { 1, 2, 3 };
            target.SaveChanges(o);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);

            Assert.AreEqual(3, actual.TestInt.Length);

            //this may be a bogus test... not sure we can gauranty the order we get elements back in... but it works so far... interesting
            Assert.AreEqual(2, actual.TestInt[1]);
        }

        [Test]
        public void IgnoreUpdateOnNullArray()
        {
            Db target = new Db();
            var a = new EntityTestArrayTypes();
            a.Id = TestIdGuid;
            a.TestString = new List<string> { "a", "b", "c" };
            target.SaveChanges(a);

            var b = new EntityTestArrayTypes();
            b.Id = TestIdGuid;
            b.TestString = null;  //if we pass a null it should be ignored (preserving the exising values)
            target.SaveChanges(b);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);
            Assert.AreEqual(3, actual.TestString.Count, "Saving a null array should NOT wipe an existing array value");
        }

        [Test]
        public void OverwriteOnEmptyArry()
        {
            Db target = new Db();
            var a = new EntityTestArrayTypes();
            a.Id = TestIdGuid;
            a.TestString = new List<string> { "a", "b", "c" };
            target.SaveChanges(a);

            var b = new EntityTestArrayTypes();
            b.Id = TestIdGuid;
            b.TestString = new List<string>();  //if we pass an empty (count == 0) array it should clear the existing values
            target.SaveChanges(b);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);
            Assert.IsNull(actual.TestString, "Saving an empty array should wipe all existing array value");
        }



        [Test]
        public void TagTest()
        {
            Db target = new Db();
            var o = new EntityTestArrayTypes();
            o.Id = TestIdGuid;
            o.Tags = new List<string>() { "Bob", "Doug", "Jane" };
            target.SaveChanges(o);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);

            Assert.AreEqual(3, actual.Tags.Count);

            //this may be a bogus test... not sure we can gauranty the order we get elements back in... but it works so far... interesting
            Assert.AreEqual("Doug", actual.Tags[1]);
        }

        [Test]
        public void DeleteTagTest()
        {
            Db target = new Db();
            var o = new EntityTestArrayTypes();
            o.Id = TestIdGuid;
            o.Tags = new List<string>() { "Bob", "Doug", "Jane" };
            target.SaveChanges(o);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);

            Assert.AreEqual(3, actual.Tags.Count);


            o.Tags.Remove("Bob");
            target.SaveChanges(o);

            var removed = target.Find<EntityTestArrayTypes>(TestIdGuid);

            Assert.AreEqual(2, removed.Tags.Count);

        }

        [Test]
        public void DeleteAllTagsTest()
        {
            Db target = new Db();
            var o = new EntityTestArrayTypes();
            o.Id = TestIdGuid;
            o.Tags = new List<string>() { "Bob", "Doug", "Jane" };
            target.SaveChanges(o);

            var actual = target.Find<EntityTestArrayTypes>(TestIdGuid);

            Assert.AreEqual(3, actual.Tags.Count);


            o.Tags.Remove("Bob");
            o.Tags.Remove("Doug");
            o.Tags.Remove("Jane");
            target.SaveChanges(o);

            var removed = target.Find<EntityTestArrayTypes>(TestIdGuid);
 
            Assert.IsNull(removed.Tags);

        }


    }
}
